﻿using System.Collections.Generic;
using CarlosAg.ExcelXmlWriter;
using SdmxMl.Common;
using SdmxMl.Manager;
using SdmxMl.Structure;

namespace SdmxMl.Excel
{
    /// <summary>
    /// Specialized class for generating Excel export of MSD 
    /// </summary>
    public class ExcelExportDSD : ExcelExportBase
    {
        #region Internal Members

        private SmManager smManager;
        private KeyFamilyType dsd;
        private int itemCount;
        private RefVarHelper varHelper;
        List<BaseDimensionType> lbd;

        #endregion

        #region C'tor

        /// <summary>C'tor with specified artefact to transform</summary>
        /// <param name="m">the DSD instance</param>
        public ExcelExportDSD(KeyFamilyType k, SmManager sm)
        {
            dsd = k;
            smManager = sm;
            // Create helper for codelist and concepts
            varHelper = new RefVarHelper(sm);
        }

        #endregion

        #region Header

        /// <summary>
        /// Generate Header row names for a report page
        /// </summary>
        private void GenerateHeaderNames()
        {
            headerColitems = new List<string>(16);

            headerColitems.Add("ConceptScheme");
            headerColitems.Add("Concept");
            headerColitems.Add("Role");

            foreach (string lg in SdmxMl.Common.LangSupport.SupportedLanguages)
                headerColitems.Add("Name_" + lg);

            headerColitems.Add("Codelist");
            headerColitems.Add("Text Format");
            headerColitems.Add("TF_Minlen");
            headerColitems.Add("TF_Maxlen");
            headerColitems.Add("TF_StartVal");
            headerColitems.Add("TF_EndVal");
            headerColitems.Add("TF_Decimal");
            headerColitems.Add("Cross Att.");
            headerColitems.Add("Att. Level");
            headerColitems.Add("Assign Stat.");
            headerColitems.Add("SourceId");
            headerColitems.Add("SourceInfo");
            headerColitems.Add("SourceRef");


            anInventory = new AnnotationInventory();

            lbd = varHelper.PrepareVarList(dsd, false);
            foreach (BaseDimensionType bd in lbd)
                anInventory.Inventory(bd.AnnotationList, false);

            anInventory.GenerateAnnotationHeader(headerColitems);
        }
        #endregion

        public override void Export()
        {
            GenerateBook("SMS", "OFS");
            GenerateWorksheetArtefact(dsd);

            GenerateHeaderNames();
            sheet = GenerateWorksheetHeader(headerColitems.ToArray(), "VAR", lbd.Count);

            itemCount = 0;
            foreach (BaseDimensionType bd in lbd)
            {
                FillRow(bd);
                ++itemCount;
            }

            // Update sheet count
            sheet.Table.ExpandedRowCount = 1 + itemCount;

        }


        protected void FillRow(BaseDimensionType bd)
        {
            if (bd != null)
            {
                WorksheetRow row = sheet.Table.Rows.Add();

                AttributeType att = bd as AttributeType;
                DimensionType dim = bd as DimensionType;

                AddCell(row, bd.ConceptSchemeInfo.FullIdent);
                AddCell(row, bd.ConceptInfo.Id);

                // Get Role
                string role = "Measure";
                if (bd == dsd.PrimaryMeasure)
                    role = "OBS";
                else if (bd is DimensionType)
                    role = "Dimension";
                else if (bd is TimeDimensionType)
                    role = "TimeDimension";
                else if (att != null)
                    role = "Attribute";
                else if (dim != null)
                    role = dim.DimKind.ToString();

                AddCell(row, role);

                // Concept name internationalized
                ConceptType c = varHelper.GetConcept(bd.ConceptInfo.Id, bd.ConceptSchemeInfo);
                FillMultilangCells(row, c.Name);

                // Codelist Ref (from dim or via concept)
                string CodelistRef = string.Empty;
                ISdmxArtefactRef aRef = varHelper.GetCodelistFullIdOfBaseDim(bd);
                if (aRef != null)
                {
                    ArtefactRefTyped art = new ArtefactRefTyped(SdmxArtefactType.CodeLists, aRef.FullIdent);
                    if (art.IsFilled)
                        CodelistRef = art.FullIdent;
                }
                AddCell(row, CodelistRef);

                // Text format
                TextFormatType tft = varHelper.GetTextFormatTypeOfBaseDim(bd);
                AddCell(row, tft.ToString());
                AddCell(row, tft.minLength);
                AddCell(row, tft.maxLength);
                AddCell(row, tft.IsNumeric ? tft.startValue : string.Empty);
                AddCell(row, tft.IsNumeric ? tft.endValue : string.Empty);
                AddCell(row, tft.IsNumeric ? tft.decimals : string.Empty);


                //Cross attach
                string cross = string.Empty;
                if (att != null)
                    cross = att.CrossSectionalAttach.ToString();
                else if (dim != null)
                    cross = dim.CrossSectionalAttach.ToString();
                AddCell(row, cross);

                // Attach Level
                string attachLevel = (att != null) ? att.AttachmentLevel.ToString() : string.Empty;
                AddCell(row, attachLevel);

                // Assignement Status
                string assign = string.Empty;
                if (att != null)
                    assign = att.AssignmentStatus.ToString();
                else if (bd is TimeDimensionType) // any dimension type inherit of it
                    assign = "Mandatory";
                else
                    assign = "Conditional";

                AddCell(row, assign);

                // Source from concept annotation
                ConceptType ct = varHelper.GetConcept(bd.ConceptInfo.Id, bd.ConceptSchemeInfo);
                string source = string.Empty;
                string sourceId = string.Empty;
                string sourceUrn = string.Empty;
                if (ct != null && ct.AnnotationList.GetAnnotationType("SOURCE") != null)
                {
                    Annotation a = ct.AnnotationList.GetAnnotationType("SOURCE");
                    sourceId = a.Title;
                    if (a.Url != null)
                        sourceUrn = UrnManager.UrnToArtefactRefTyped(a.Url.ToString()).FullIdent;
                    source = a.Text.GetFirst();
                }
                AddCell(row, sourceId);
                AddCell(row, source);
                AddCell(row, sourceUrn);

                // All annotations
                AddAnnotations(row, bd.AnnotationList);
            }

        }
        private void FillMultilangCells(WorksheetRow row, MultiLang ml)
        {
            if (ml != null && ml.IsEmpty == false)
            {
                foreach (string lg in SdmxMl.Common.LangSupport.SupportedLanguages)
                    AddCell(row, ml.GetIfDefinedForLanguage(lg));
            }
            else
            {
                foreach (string lg in SdmxMl.Common.LangSupport.SupportedLanguages)
                    AddCell(row, string.Empty);
            }
        }



    }
}
